Skip to main content

Web API Reference

This API is implemented in Wolfram Language and wired through AppExtensions' HTTP handler. All endpoints live under /api/….

TLDR;

  • Base URL: /api/

  • Auth: none

  • CORS: Access-Control-Allow-Origin: * (enabled by the server)

  • Formats:

    • Requests: JSON in the body for most endpoints
    • Responses: JSON (often simple strings/booleans), HTTP 200 on success
    • Errors: HTTP 409 with a JSON string message (e.g. "Notebook is missing")

Index endpoint

GET /api/

Returns the top‑level groups available on this server.

Response200 OK

[
"/api/kernels/",
"/api/transactions/",
"/api/frontendobjects/",
"/api/extensions/",
"/api/ready/",
"/api/notebook/",
"/api/alphaRequest/"
]

Readiness

GET /api/ready/

Health check.

Response200 OK

{"ReadyQ": true}

Wolfram|Alpha passthrough

POST /api/alphaRequest/

Run a Wolfram|Alpha query and return its ShortAnswer.

Request body

{ "Query": "integrate x^2" }

Response200 OK

"x^3/3"

Errors (e.g., malformed body) come back as HTTP 409 with a JSON string message.


Notebook API

GET /api/notebook/

Returns the available subroutes:

[
"/api/notebook/list/",
"/api/notebook/create/",
"/api/notebook/create/pull/",
"/api/notebook/cells/"
]

GET /api/notebook/list/

List known notebooks.

Response200 OK

[
{ "Id": "<hash>", "Opened": true, "Path": "/path/to.nb" },
{ "Id": "<hash>", "Opened": false, "Path": "/path/other.nb" }
]

POST /api/notebook/create/

Create a new notebook in the active UI session.

Prerequisites

  • A UI window must be open

Response200 OK

"<createUid>"

The returned createUid is a temporary id used to pull the real notebook id.

POST /api/notebook/create/pull/

Exchange the temporary createUid for the new notebook’s hash.

Request body

{ "Id": "<createUid>" }

Response200 OK

"<notebookId>"

The server pushes the notebook hash to an internal queue when the UI actually creates it. Poll this endpoint until it resolves.


Notebook cells

GET /api/notebook/cells/ returns the following subroutes:

[
"/api/notebook/cells/list/",
"/api/notebook/cells/get/",
"/api/notebook/cells/focused/",
"/api/notebook/cells/set/",
"/api/notebook/cells/add/",
"/api/notebook/cells/evaluate/",
"/api/notebook/cells/project/",
"/api/notebook/cells/delete/"
]

POST /api/notebook/cells/list/

List cells in a notebook.

Request body

{ "Notebook": "<notebookHash>" }

Response200 OK

[
{ "Id": "<cellId>", "Type": "Input", "State": "…", "Display": "codemirror" },
{ "Id": "<cellId>", "Type": "Output", "State": "…", "Display": "html" }
]

Errors409 with "Notebook is missing" when the id is unknown.

POST /api/notebook/cells/focused/

Get the focused cell (or the last cell if none is focused).

Request body

{ "Notebook": "<notebookHash>" }

Response200 OK

{ "Id": "<cellId>", "Type": "Input", "State": "…", "Display": "codemirror" }

POST /api/notebook/cells/get/

Fetch a cell’s raw Data.

Request body

{ "Cell": "<cellId>" }

Response200 OK

"(* the cell's content as a string or JSON-encoded expression *)"

POST /api/notebook/cells/delete/

Delete a cell.

Request body

{ "Cell": "<cellId>" }

Response200 OK

"Removed"

POST /api/notebook/cells/set/

Update a cell’s Data field. If the notebook UI is open, the change is applied live.

Request body

{ "Cell": "<cellId>", "Data": "…new content…" }

Responses200 OK

"Data field was updated live in the notebook"

or

"Data field was updated"

Errors409 with "Cannot edit output cells" when editing is disallowed for that cell.

POST /api/notebook/cells/add/

Add a new Input cell to a notebook.

Request body

{
"Notebook": "<notebookHash>",
"Data": "…initial content…",
"Id": "<optionalCellId>",
"After": "<optionalcellIdToInsertAfter>"
}

Response200 OK

"Added to the end of the notebook"

—or—

"Added after <cellId>"

POST /api/notebook/cells/evaluate/

Evaluate a cell in an open notebook UI.

Request body

{ "Cell": "<cellId>" }

Response200 OK

"Submitted"

Errors409 with "Can't evaluate cell in a closed notebook. Use transactions".

POST /api/notebook/cells/project/

Project/evaluate a cell (variant of evaluate/).

Request body

{ "Cell": "<cellId>" }

Responses200 OK

"Evaluation started"

Errors409 with "Can't evaluate cell in a closed notebook".


Frontend Objects

GET /api/frontendobjects/

[ "/api/frontendobjects/get/" ]

POST /api/frontendobjects/get/

Resolve a frontend object by UId. This is a two‑phase poll:

  1. First call returns { "Resolved": false } and kicks off resolution in a ready kernel.
  2. Poll until you receive { "Resolved": true, "Data": "<ExpressionJSON string>" }.

Request body

{
"UId": "<objectId>",
"Kernel": "<optionalKernelHash>"
}

Responses200 OK

{ "Resolved": false }

—or—

{ "Resolved": true, "Data": "{\"…ExpressionJSON…\"}" }

Errors409 with messages like "Kernel is missing" when no suitable kernel is available.


Transactions API

Batch/evaluate code without an open notebook via transactions.

GET /api/transactions/

[
"/api/transactions/create/",
"/api/transactions/get/",
"/api/transactions/delete/",
"/api/transactions/list/"
]

POST /api/transactions/create/

Create and submit a transaction to a specific kernel.

Request body

{
"Kernel": "<kernelHash>",
"Data": "(* Wolfram Language code or serialized input *)"
}

Response200 OK

"<transactionHash>"

Errors409 with "Kernel is missing".

POST /api/transactions/get/

Fetch transaction status and results.

Request body

{ "Hash": "<transactionHash>" }

Response200 OK

{
"Hash": "<transactionHash>",
"State": "Evaluation" | "Idle" | "Error" | "Undefined",
"Result": [
{ "Data": "…", "Type": "Output", "Display": "codemirror" },
{ "Data": "…", "Type": "Output", "After": "<cellId>", "Display": "html" }
]
}
  • Each result is appended as the transaction emits outputs. If the producer attaches a Meta object, its keys are merged into the result.

POST /api/transactions/list/

List transactions (id + coarse state).

Response200 OK

[
{ "Hash": "<tx>", "State": "Idle" },
{ "Hash": "<tx>", "State": "Evaluation" }
]

POST /api/transactions/delete/

Delete a finished/obsolete transaction.

Request body

{ "Hash": "<transactionHash>" }

Response200 OK

true

Kernels API

Manage and query kernels, and make asynchronous function calls.

GET /api/kernels/

[
"/api/kernels/list/",
"/api/kernels/restart/",
"/api/kernels/abort/",
"/api/kernels/get/",
"/api/kernels/create/",
"/api/kernels/unlink/",
"/api/kernels/init/",
"/api/kernels/deinit/",
"/api/kernels/fetch/"
]

GET /api/kernels/list/

List available kernels.

Response200 OK

[
{
"Hash": "<kernelHash>",
"State": "…",
"ReadyQ": true,
"Name": "WolframKernel",
"ContainerReadyQ": true
}
]

POST /api/kernels/get/

Get one kernel by hash.

Request body

{ "Hash": "<kernelHash>" }

Response200 OK — same shape as items in list/.

POST /api/kernels/restart/

Restart a kernel.

Request body

{ "Hash": "<kernelHash>" }

Response200 OK

true

POST /api/kernels/abort/

Abort the current evaluation on a kernel.

Request body

{ "Hash": "<kernelHash>" }

Response200 OK

true

POST /api/kernels/init/

Initialize a kernel with environment settings.

Request body

{ "Hash": "<kernelHash>" }

Response200 OK

true

POST /api/kernels/deinit/

De‑initialize a kernel.

Request body

{ "Hash": "<kernelHash>" }

Response200 OK

true

Asynchronous function calls (fetch/)

POST /api/kernels/fetch/

Call a Wolfram Language symbol with arguments asynchronously in a ready kernel.

Request body

{
"Symbol": "Package`FunctionName",
"Args": [ /* positional args */ ],
"Kernel": "<optionalKernelHash>"
}

Response200 OK

"<requestUid>"

POST /api/kernels/fetch/get/

Poll for the result of a prior fetch/.

Request body

{ "UId": "<requestUid>" }

Responses200 OK

{ "ReadyQ": false }

—or—

{ "ReadyQ": true, "Result": "{\"…ExpressionJSON…\"}" }

Errors409 with "UId is not provided or is missing".

If the target function returns a Promise on the kernel side, the API resolves that promise and returns its ExpressionJSON payload when ready.

Not implemented

  • POST /api/kernels/create/409 "Not implemented"
  • POST /api/kernels/unlink/409 "Not implemented"

Extensions & CDN

These endpoints help you discover and load WLJS extensions and styles.

GET /api/cdn/

[
"/api/cdn/list/",
"/api/cdn/get/js/",
"/api/cdn/get/styles/"
]

POST /api/cdn/get/js/

Return a list of CDN URLs for the requested packages’ JavaScript (plus required shims).

Request body — array of package keys

["wljs-some-package", "..." ]

Response200 OK

[
"https://cdn.skypack.dev/twind/shim",
"https://cdn.jsdelivr.net/gh/<repo>@<branch>/<path>.js",
"https://cdn.jsdelivr.net/gh/<this-repo>@<branch>/assets/polyfill.js"
]

GET /api/cdn/get/styles/

Return a list of CDN URLs for stylesheets, including the built‑in minimal theme.

Response200 OK

[
"https://cdn.jsdelivr.net/gh/<this-repo>@<branch>/assets/minimal.css"
]

GET /api/cdn/list/

List all enabled packages that expose a minjs entry.

Response200 OK

[ "wljs-foo", "wljs-bar", "…" ]

GET /api/extensions/

[
"/api/extensions/list/",
"/api/extensions/get/minjs/",
"/api/extensions/bundle/minjs/",
"/api/extensions/get/styles/",
"/api/extensions/bundle/styles/"
]

GET /api/extensions/list/

Discover enabled extensions and versions.

Response200 OK

[
{ "name": "wljs-foo", "version": "1.2.3" },
{ "name": "common-css", "version": "0.1" }
]

POST /api/extensions/get/minjs/

Return URL‑encoded source blobs for each package’s minjs payload (not URLs).

Request body — array of package keys (the special "common-css" key is ignored here)

["wljs-foo", "wljs-bar"]

Response200 OK

[ "function(){…}%7D", "(function(){…})%3B" ]

POST /api/extensions/bundle/minjs/

Return a single URL‑encoded JS bundle that concatenates all enabled packages’ minjs payloads.

Response200 OK

"/* wljs-api bundler */%0D%0A%7B%0D%0A…%0D%0A%7D"

POST /api/extensions/get/styles/

Return URL‑encoded CSS blobs for each requested package’s styles. If the list includes "common-css", the server also appends its built‑in common.css.

Request body

["wljs-foo", "common-css"]

Response200 OK

[ "body%7B…%7D", "/*common*/%0A…" ]

POST /api/extensions/bundle/styles/

Return a single URL‑encoded CSS bundle of all enabled packages’ styles plus the built‑in common styles.

Response200 OK

".class%7B…%7D%0A%0A/*common*/%0A…"

Some packages are blacklisted from the JS bundle by design (e.g. wljs-markdown-support, wljs-plotly, wljs-mermaid-support, etc.).


Error handling

  • Success → HTTP 200, JSON body (may be a string or boolean)
  • Failure → HTTP 409, body is a JSON string with the message (e.g., "Kernel is missing").

Common messages include:

  • "Notebook is missing", "Cell is missing"
  • "Kernel is missing" or "Kernel is missing or not ready"
  • "Cannot edit output cells"
  • "Can't evaluate cell in a closed notebook. Use transactions"
  • "Not implemented"

Types & fields

  • Ids are opaque hashes: NotebookId, CellId, KernelHash, TransactionHash, async request/resolve ids → UId.
  • Kernel fields: State (string), ReadyQ (boolean), ContainerReadyQ (boolean), Name (string)
  • Transaction fields: State is one of "Evaluation" | "Idle" | "Error" | "Undefined"; Result is a list of output objects with at least Data and Type ("Output"). Optional keys: Display, After, Before, custom meta.
  • Cell fields: Type is typically "Input" or "Output"; Display hints at rendering (e.g. "codemirror", "html").

Examples

See this notebook: WebAPI Notebook.wln

Notes & caveats

  • Consider hash = id
  • Many endpoints require a ready kernel or an opened notebook; otherwise you’ll receive a 409 with a helpful message.
  • Some responses intentionally return URL‑encoded source blobs instead of URLs (extensions/styles). Decode on the client if you plan to inline them.
  • The server sets Content-Length, Connection: Keep-Alive, and CORS headers on responses.
  • There are a few implementation quirks (e.g., cell‑editing rules and insertion logic) that may change; rely on the messages the server returns.